/*$Id: ValidatedTextBox.java 237 2008-04-02 01:46:13Z lrsmith $*/
package com.leetech.gwt.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A TextBox with built in validation of content using java.util.regex.Pattern.
 * The css of the box is modified with "state-invalid" to allow the box's
 * appearance to change if invalid content is added. An empty state is also
 * detected for required field verification upon submission of a form.
 */
public class ValidatedTextBox extends TextBox {

	// Static initialization-------------------------------------------
	/** Valid state constant. */
	public static int STATE_VALID = 0;
	/** Empty state constant. */
	public static int STATE_EMPTY = -1;
	/** Invalid state constant. */
	public static int STATE_INVALID = 1;
	/** css modifier for invalid state. */
	public static String CSS_STATE_INVALID = "state-invalid";

	// Instance variables----------------------------------------------
	/**
	 * The state of the text box with value STATE_VALID, STATE_EMPTY or
	 * STATE_INVALID.
	 */
	private int boxState = STATE_EMPTY;
	/** A descriptive label next to the text box */
	private Label label;
    private String regExp;
    ChangeListener validateListener;

	// Constructors----------------------------------------------------
	/**
	 * <p>
	 * Constructs a ValidatedTextBox using the regExp to validate content. Box
	 * is assumed to be empty if it only contains white space. To ignore white
	 * space at the beginning and end of the box prepend and append the sequence:
	 * <code>\s*</code>
	 * </p>
	 */
	public ValidatedTextBox( final String regExp) {
		this.regExp = regExp;
		validateListener =  new ChangeListener() {

			public void onChange(Widget sender) {
				TextBox box = (TextBox) sender;
				// Check for emptiness
				if (box.getText().trim().equals("")) {
					setStateEmpty();
					// Validate text
				} else if (box.getText().matches(ValidatedTextBox.this.regExp)) {
					setStateValid();
				}
				// validation failed
				else {
					setStateInvalid();
				}
			};
		};
		addChangeListener(validateListener);
	}
    // Methods---------------------------------------------------------
	/** Set the box state to be invalid */
	private void setStateInvalid() {
		boxState = STATE_INVALID;
		addStyleDependentName(CSS_STATE_INVALID);
		GWT.log("ValidatedTextBox: invalid",null);
	}

	/** Set the box state to be valid */
	private void setStateValid() {
		removeStyleDependentName(CSS_STATE_INVALID);
		boxState = STATE_VALID;
		GWT.log("ValidatedTextBox: valid",null);
	}

	/** Set the box state to be empty */
	private void setStateEmpty() {
		removeStyleDependentName(CSS_STATE_INVALID);
		boxState = STATE_EMPTY;
		GWT.log("ValidatedTextBox: empty",null);
	}

	/**
	 * Returns the state of the box as one of the following state constants:
	 * STATE_EMPTY, STATE_VALID, or STATE_INVALID
	 */
	public int getValidationState() {
		return boxState;
	}

	/**
	 * Returns a panel with the widget and a descriptive Label with content
	 * specified in the constructor.
	 */
	public Panel getLabledPanel() {
		Panel pan = new HorizontalPanel();
		pan.add(label);
		pan.add(this);

		return pan;
	}
	/**
	 * Returns the label associated with the text box
	 */
	public Label getLabel(){
			return label;
	}
	public void setRegExp(String regExp){
	    this.regExp = regExp;
	    validateListener.onChange(this);
	}

}
